% TODO proof-reading
\subsection{Возврат значения}

Наверное, самая простая из всех возможных функций на Java это та, что возвращает 
некоторое значение.

О, и мы не должны забывать, что в Java нет \q{свободных} функций в общем смысле,
это \q{методы}.

Каждый метод принадлежит какому-то классу, так что невозможно объявить метод 
вне какого-либо класса.

Но мы все равно будем называть их \q{функциями}, для простоты.

\begin{lstlisting}[style=customjava]
public class ret
{
	public static int main(String[] args) 
	{
		return 0;
	}
}
\end{lstlisting}

Компилируем это:

\begin{lstlisting}
javac ret.java
\end{lstlisting}

\dots и декомпилирую используя стандартную утилиту в Java:

\begin{lstlisting}
javap -c -verbose ret.class
\end{lstlisting}

И получаем:

\begin{lstlisting}[caption=JDK 1.7 (excerpt)]
  public static int main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=1, args_size=1
         0: iconst_0      
         1: ireturn       
\end{lstlisting}

Разработчики Java решили, что 0 это самая используемая константа в программировании,
так что здесь есть отдельная однобайтная инструкция \GTT{iconst\_0}, заталкивающая 0 в стек
\footnote{Так же как и в MIPS, где для нулевой константы имеется отдельный регистр: \myref{MIPS_zero_register}.}.

Здесь есть также \GTT{iconst\_1} (заталкивающая 1), \GTT{iconst\_2}, итд, 
вплоть до \GTT{iconst\_5}.
Есть также \GTT{iconst\_m1} заталкивающая -1.

Стек также используется в JVM для передачи данных в вызывающие ф-ции, и также для возврата значений.
Так что \GTT{iconst\_0} заталкивает 0 в стек.
\GTT{ireturn} возвращает целочисленное значение (\IT{i} в названии означает \IT{integer}) из \ac{TOS}.

Немного перепишем наш пример, теперь возвращаем 1234:

\begin{lstlisting}[style=customjava]
public class ret
{
	public static int main(String[] args)
	{
		return 1234;
	}
}
\end{lstlisting}

\dots получаем:

\begin{lstlisting}[caption=JDK 1.7 (excerpt)]
  public static int main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=1, args_size=1
         0: sipush        1234
         3: ireturn       
\end{lstlisting}

\GTT{sipush} (\IT{short integer}) заталкивает значение 1234 в стек.
\IT{short} в имени означает, что 16-битное значение будет заталкиваться в стек. 

Число 1234 действительно помещается в 16-битное значение.

Как насчет б\'{о}льших значений?

\begin{lstlisting}[style=customjava]
public class ret
{
	public static int main(String[] args) 
	{
		return 12345678;
	}
}
\end{lstlisting}

\begin{lstlisting}[caption=Constant pool]
...
   #2 = Integer            12345678
...
\end{lstlisting}

\begin{lstlisting}
  public static int main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=1, args_size=1
         0: ldc           #2                  // int 12345678
         2: ireturn       
\end{lstlisting}

Невозможно закодировать 32-битное число в опкоде какой-либо JVM-инструкции, 
разработчики не оставили такой возможности.

Так что 32-битное число 12345678 сохранено в так называемом \q{constant pool} (пул констант),
который, так скажем, является библиотекой наиболее используемых констант (включая строки, объекты,
итд).

Этот способ передачи констант не уникален для JVM.

MIPS, ARM и прочие RISC-процессоры не могут кодировать 32-битные числа в 32-битных опкодах,
так что код для RISC-процессоров (включая MIPS и ARM) должен конструировать значения 
в несколько шагов, или держать их в сегменте данных:
\myref{ARM_big_constants}, \myref{MIPS_big_constants}.

Код для MIPS также традиционно имеет пул констант, называемый \q{literal pool}, это сегменты
с названиями \q{.lit4} (для хранения 32-битных чисел с плавающей точкой одинарной точности) и
\q{.lit8}(для хранения 64-битных чисел с плавающей точкой двойной точности).

Попробуем некоторые другие типы данных!

Boolean:

\begin{lstlisting}[style=customjava]
public class ret
{
	public static boolean main(String[] args) 
	{
		return true;
	}
}
\end{lstlisting}

\begin{lstlisting}
  public static boolean main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=1, args_size=1
         0: iconst_1      
         1: ireturn       
\end{lstlisting}

Этот JVM-байткод не отличается от того, что возвращает целочисленную 1.

32-битные слоты данных в стеке также используются для булевых значений, как в \CCpp.

Но нельзя использовать возвращаемое значение булевого типа как целочисленное и наоборот --- информация 
о типах сохраняется в class-файлах и проверяется при запуске.

Та же история с 16-битным \IT{short}:

\begin{lstlisting}[style=customjava]
public class ret
{
	public static short main(String[] args) 
	{
		return 1234;
	}
}
\end{lstlisting}

\begin{lstlisting}
  public static short main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=1, args_size=1
         0: sipush        1234
         3: ireturn       
\end{lstlisting}

\dots и \IT{char}!

\begin{lstlisting}[style=customjava]
public class ret
{
	public static char main(String[] args) 
	{
		return 'A';
	}
}
\end{lstlisting}

\begin{lstlisting}
  public static char main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=1, args_size=1
         0: bipush        65
         2: ireturn       
\end{lstlisting}

\INS{bipush} означает \q{push byte}.

Нужно сказать, что \IT{char} в Java, это 16-битный символ в кодировке UTF-16,
и он эквивалентен \IT{short}, но ASCII-код символа \q{A} это 65, и можно воспользоваться
инструкцией для передачи байта в стек.

Попробуем также \IT{byte}:

\begin{lstlisting}[style=customjava]
public class retc
{
	public static byte main(String[] args) 
	{
		return 123;
	}
}
\end{lstlisting}

\begin{lstlisting}
  public static byte main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=1, args_size=1
         0: bipush        123
         2: ireturn       
\end{lstlisting}

Кто-то может спросить, зачем заморачиваться использованием 16-битного типа \IT{short}, который
внутри все равно 32-битный integer?

Зачем использовать тип данных \IT{char}, если это то же самое что и тип \IT{short}?

Ответ прост: для контроля типов данных и читабельности исходников.

\IT{char} может быть эквивалентом \IT{short}, но мы быстро понимаем, что это ячейка
для символа в кодировке UTF-16, а не для какого-то другого целочисленного значения.

Когда используем \IT{short}, мы можем показать всем, что диапазон этой переменной 
ограничен 16-ю битами.

Очень хорошая идея использовать тип \IT{boolean} где нужно, 
вместо \IT{int} для тех же целей, как это было в Си.

В Java есть также 64-битный целочисленный тип:

\begin{lstlisting}[style=customjava]
public class ret3
{
	public static long main(String[] args)
	{
		return 1234567890123456789L;
	}
}
\end{lstlisting}

\begin{lstlisting}[caption=Constant pool]
...
   #2 = Long               1234567890123456789l
...
\end{lstlisting}

\begin{lstlisting}
  public static long main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: ldc2_w        #2                  // long 1234567890123456789l
         3: lreturn       
\end{lstlisting}

64-битное число также хранится в пуле констант, \INS{ldc2\_w} загружает его и \INS{lreturn} 
(\IT{long return}) возвращает его.

Инструкция \INS{ldc2\_w} также используется для загрузки чисел с плавающей точкой двойной 
точности (которые также занимают 64 бита) из пула констант:

\begin{lstlisting}[style=customjava]
public class ret
{
	public static double main(String[] args)
	{
		return 123.456d;
	}
}
\end{lstlisting}

\begin{lstlisting}[caption=Constant pool]
...
   #2 = Double             123.456d
...
\end{lstlisting}

\begin{lstlisting}
  public static double main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: ldc2_w        #2                  // double 123.456d
         3: dreturn       
\end{lstlisting}

\INS{dreturn} означает \q{return double}.

И наконец, числа с плавающей точкой одинарной точности:

\begin{lstlisting}[style=customjava]
public class ret
{
	public static float main(String[] args)
	{
		return 123.456f;
	}
}
\end{lstlisting}

\begin{lstlisting}[caption=Constant pool]
...
   #2 = Float              123.456f
...
\end{lstlisting}

\begin{lstlisting}
  public static float main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=1, args_size=1
         0: ldc           #2                  // float 123.456f
         2: freturn       
\end{lstlisting}

Используемая здесь инструкция \INS{ldc} та же, что и для загрузки 32-битных целочисленных чисел
из пула констант.

\INS{freturn} означает \q{return float}.

А что насчет тех случаев, когда функция ничего не возвращает?

\begin{lstlisting}[style=customjava]
public class ret
{
	public static void main(String[] args) 
	{
		return;
	}
}
\end{lstlisting}

\begin{lstlisting}
  public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=0, locals=1, args_size=1
         0: return        
\end{lstlisting}

Это означает, что инструкция \INS{return} используется для возврата управления 
без возврата какого-либо значения.

Зная все это, по последней инструкции очень легко определить тип возвращаемого 
значения функции (или метода).
